
use std::ops::Deref;

// Deref trait
struct MyBox<T>(T);

impl<T> MyBox<T> {
    fn new(x:T) -> MyBox<T> {
        MyBox(x)
    }
}

impl<T> Deref for MyBox<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

// Drop trait
struct CustomSmartPointer {
    data: String,
}

impl Drop for CustomSmartPointer {
    fn drop(&mut self) {
        println!("Dropping CustomSmartPointer with data '{}'!", self.data);
    }
}

fn main() {
    // Dref trait
    println!("Hello, world!");
    let x = 5;
    let y = MyBox::new(x);

    assert_eq!(5, x);
    assert_eq!(5, *y);

    // Drop trait
    let c = CustomSmartPointer {data: String::from("my stuff")};
    // drop(c);
    let d = CustomSmartPointer {data: String::from("other stuff")};
    println!("CustomSmartPoints created.");
}
